﻿using System;
using System.Reflection;
using System.Runtime.Remoting;
using java = biz.ritter.javapi;
using biz.ritter.javapi.io;

namespace biz.ritter.javapi.lang
{
    /// <summary>
    /// Summary description for Function.
    /// </summary>
    [Serializable]
    public class Function : MarshalByRefObject
    {
        public delegate double FuncArrParam(params double[] parameters);

        delegate double Func0Param();
        delegate double Func1Param(double p);
        delegate double Func2Param(double p1, double p2);

        Delegate funcToCall = null;
        string name;

        public Function(string name, FuncArrParam functionToCall)
        {
            this.name = name;
            funcToCall = functionToCall;
        }

        public Function(string name, MethodInfo method, object instance)
        {
            this.name = name;
            int paramCount = method.GetParameters().Length;

            Type typeToCreate;
            switch (paramCount)
            {
                case 0:
                    typeToCreate = typeof(Func0Param);
                    break;
                case 1:
                    typeToCreate = typeof(Func1Param);
                    break;
                case 2:
                    typeToCreate = typeof(Func2Param);
                    break;
                default:
                    throw new Exception(String.Format("{0} parameters not supported", paramCount));
            }
            if (instance == null)
            {
                funcToCall = Delegate.CreateDelegate(typeToCreate, method);
            }
            else
            {
                funcToCall = Delegate.CreateDelegate(typeToCreate, instance, method.Name);
            }

        }

        public override string ToString()
        {
            return name;
        }

        public string Name
        {
            get
            {
                return name;
            }
        }

        public double Invoke(params double[] parameters)
        {
            if (funcToCall.GetType() == typeof(FuncArrParam))
                return ((FuncArrParam)funcToCall)(parameters);

            if (funcToCall.GetType() == typeof(Func0Param))
                return ((Func0Param)funcToCall)();

            if (funcToCall.GetType() == typeof(Func1Param))
                return ((Func1Param)funcToCall)(parameters[0]);

            if (funcToCall.GetType() == typeof(Func2Param))
                return ((Func2Param)funcToCall)(parameters[0], parameters[1]);

            throw new Exception("Can't call function in invoke");
        }
    }
}
